#include <cstring>
#include <iostream>
#include <thread>
#include <unistd.h>

// =============== Windows ==============
#if defined(_WIN32) || defined(_WIN64)
#include <cstdint>
#include <ws2tcpip.h>
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
#define close(sock) closesocket(sock)
typedef SOCKET socket_t;
#define INVALID_SOCKET_VALUE INVALID_SOCKET
using ushort = unsigned short;
// =========  Unix/Linux/Macos  =========
#else
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/select.h>
#define INVALID_SOCKET_VALUE -1
typedef int socket_t;
#endif

#define BUFFER_SIZE 1024

// 编译：
// Linux:   g++ -std=c++11 -o tcp_client_linux.exe tcp_client.cpp
// Windows: g++ -std=c++11 -o tcp_client_windows.exe tcp_client.cpp -lws2_32
int main(int argc, char *argv[]) {
	if (argc != 3) {
		std::cerr << "Usage: " << argv[0] << " <server_ip> <server_port>" << std::endl;
		return -1;
	}

	const char *serverIP   = argv[1];
	int         serverPort = atoi(argv[2]);

	// 初始化 Winsock（仅 Windows）
#if defined(_WIN32) || defined(_WIN64)
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		std::cerr << "WSAStartup failed!" << std::endl;
		return -1;
	}
#endif

	// 创建 TCP socket
	socket_t fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (fd == INVALID_SOCKET_VALUE) {
		std::cerr << "Create socket failed" << std::endl;
		return -1;
	}

	// 设置服务器地址
	struct sockaddr_in serverAddr;
	serverAddr.sin_family      = AF_INET;
	serverAddr.sin_port        = htons(serverPort);
	serverAddr.sin_addr.s_addr = inet_addr(serverIP);

	// 连接服务器
	if (connect(fd, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0) {
		std::cerr << "Connect to server failed!" << std::endl;
		close(fd);
		return -1;
	}
	std::cout << "Connected to server " << serverIP << ":" << serverPort << std::endl;

	// 接收线程（非阻塞）
	std::thread receiver([&]() {
		char buffer[BUFFER_SIZE];
		while (true) {
			ssize_t n = recv(fd, buffer, BUFFER_SIZE, 0);
			if (n <= 0) {
				std::cerr << "Server disconnected or error occurred." << std::endl;
				break;
			}
			std::cout.write(buffer, n);
			std::cout << std::endl << std::flush;
		}
	});

	// 发送线程（阻塞，等待用户输入）
	std::string message;
	while (std::getline(std::cin, message)) {
		if (!message.empty()) {
			ssize_t sentBytes = send(fd, message.c_str(), message.size(), 0);
			if (sentBytes < 0) {
				std::cerr << "Send failed!" << std::endl;
				break;
			}
		}
	}

	// 清理资源
	close(fd);
	receiver.join();

#if defined(_WIN32) || defined(_WIN64)
	WSACleanup();
#endif

	return 0;
}
